#include <iostream>
#include <pthread.h>
#include <string>
#include <vector>
#include <unistd.h>
#include "LockGuard.hpp"
using namespace std;

#define NUM 5

int tickets = 100;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

class ThreadData
{
public:
    // ThreadData(int num, pthread_mutex_t* lock)
    //     : _lock(lock)
    // {
    //     _threadname = "Thread_" + to_string(num);
    // }

    ThreadData(int num)
    {
        _threadname = "Thread_" + to_string(num);
    }


    string getThreadname()
    {
        return _threadname;
    }

    // pthread_mutex_t* getLock()
    // {
    //     return _lock;
    // }     

private:
    string _threadname;
    // pthread_mutex_t* _lock;
};

void* buyTicket(void* argc)
{
    ThreadData* td = static_cast<ThreadData*>(argc);
    while(true)
    {
        //pthread_mutex_lock(td->getLock());
        //pthread_mutex_lock(&lock);
        {
            LockGuard lockguard(&lock);
            if(tickets > 0)
            {
                usleep(1000);
                printf("Thread %p, %s buy a ticket %d\n", pthread_self(), td->getThreadname().c_str(), tickets);
                tickets--;
                //pthread_mutex_unlock(td->getLock());
                pthread_mutex_unlock(&lock);

                // 买完票以后需要其他动作，不能立即继续买票
                // 锁分配不均匀 其他线程会出现饥饿现象
                // 现象 ： 一个线程连续买了几百、几千，甚至全部的票
                usleep(15);
            }
            else
            {
                //pthread_mutex_unlock(td->getLock());
                //pthread_mutex_unlock(&lock);
                break;
            }
        }
    }
    printf("%s quit....\n", td->getThreadname().c_str());
}


int main()
{
    //pthread_mutex_t lock;
    //pthread_mutex_init(&lock, nullptr);
    vector<ThreadData*> tds;
    vector<pthread_t> tids;
    // 创建线程
    for(int i = 1; i <= NUM; i++)
    {
        //ThreadData* td = new ThreadData(i, &lock);
        ThreadData* td = new ThreadData(i);
        tds.push_back(td);

        pthread_t tid;
        pthread_create(&tid, nullptr, buyTicket, td);
        tids.push_back(tid);
    }

    for(auto tid : tids)
    {
        pthread_join(tid, nullptr);
    }

    for(auto td : tds)
    {
        delete td;
    }

    //pthread_mutex_destroy(&lock);

    return 0;
}
